home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _07AF93ACB3B04D49955E13EE2A9D4691 < prev    next >
Encoding:
Text File  |  2002-06-05  |  22.9 KB  |  1,005 lines

  1. // Copyright (C) 2001-2002 Raven Software
  2. //
  3. // ui_players.c
  4.  
  5. #include "ui_local.h"
  6. #include "..\ghoul2\g2.h"
  7.  
  8.  
  9. #define UI_TIMER_GESTURE        2300
  10. #define UI_TIMER_JUMP            1000
  11. #define UI_TIMER_LAND            130
  12. #define UI_TIMER_WEAPON_SWITCH    300
  13. #define UI_TIMER_ATTACK            500
  14. #define    UI_TIMER_MUZZLE_FLASH    20
  15. #define    UI_TIMER_WEAPON_DELAY    250
  16.  
  17. #define JUMP_HEIGHT                56
  18.  
  19. #define SWINGSPEED                0.3f
  20.  
  21. #define SPIN_SPEED                0.9f
  22. #define COAST_TIME                1000
  23.  
  24.  
  25. static int            dp_realtime;
  26. static float        jumpHeight;
  27.  
  28.  
  29. /*
  30. ===============
  31. UI_ForceLegsAnim
  32. ===============
  33. */
  34. static void UI_ForceLegsAnim( playerInfo_t *pi, int anim ) 
  35. {
  36.     pi->legsAnim = ( ( pi->legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
  37.  
  38.     if ( anim == LEGS_JUMP ) 
  39.     {
  40.         pi->legsAnimationTimer = UI_TIMER_JUMP;
  41.     }
  42. }
  43.  
  44.  
  45. /*
  46. ===============
  47. UI_SetLegsAnim
  48. ===============
  49. */
  50. static void UI_SetLegsAnim( playerInfo_t *pi, int anim ) {
  51.     if ( pi->pendingLegsAnim ) {
  52.         anim = pi->pendingLegsAnim;
  53.         pi->pendingLegsAnim = 0;
  54.     }
  55.     UI_ForceLegsAnim( pi, anim );
  56. }
  57.  
  58.  
  59. /*
  60. ===============
  61. UI_ForceTorsoAnim
  62. ===============
  63. */
  64. static void UI_ForceTorsoAnim( playerInfo_t *pi, int anim ) 
  65. {
  66.     pi->torsoAnim = ( ( pi->torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
  67. }
  68.  
  69.  
  70. /*
  71. ===============
  72. UI_SetTorsoAnim
  73. ===============
  74. */
  75. static void UI_SetTorsoAnim( playerInfo_t *pi, int anim ) {
  76.     if ( pi->pendingTorsoAnim ) {
  77.         anim = pi->pendingTorsoAnim;
  78.         pi->pendingTorsoAnim = 0;
  79.     }
  80.  
  81.     UI_ForceTorsoAnim( pi, anim );
  82. }
  83.  
  84.  
  85. /*
  86. ===============
  87. UI_TorsoSequencing
  88. ===============
  89. */
  90. static void UI_TorsoSequencing( playerInfo_t *pi ) 
  91. {
  92.     int        currentAnim;
  93.  
  94.     currentAnim = pi->torsoAnim & ~ANIM_TOGGLEBIT;
  95.  
  96.     if ( pi->torsoAnimationTimer > 0 ) 
  97.     {
  98.         return;
  99.     }
  100. }
  101.  
  102.  
  103. /*
  104. ===============
  105. UI_LegsSequencing
  106. ===============
  107. */
  108. static void UI_LegsSequencing( playerInfo_t *pi ) 
  109. {
  110.     int        currentAnim;
  111.  
  112.     currentAnim = pi->legsAnim & ~ANIM_TOGGLEBIT;
  113.  
  114.     if ( pi->legsAnimationTimer > 0 ) 
  115.     {
  116.         if ( currentAnim == LEGS_JUMP ) 
  117.         {
  118.             jumpHeight = JUMP_HEIGHT * sin( M_PI * ( UI_TIMER_JUMP - pi->legsAnimationTimer ) / UI_TIMER_JUMP );
  119.         }
  120.         return;
  121.     }
  122. }
  123.  
  124. /*
  125. ===============
  126. UI_SetLerpFrameAnimation
  127. ===============
  128. */
  129. static void UI_SetLerpFrameAnimation( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation ) {
  130.     animation_t    *anim;
  131.  
  132.     lf->animationNumber = newAnimation;
  133.     newAnimation &= ~ANIM_TOGGLEBIT;
  134.  
  135.     if ( newAnimation < 0 || newAnimation >= MAX_ANIMATIONS ) {
  136.         trap_Error( va("Bad animation number: %i", newAnimation) );
  137.     }
  138.  
  139.     anim = &ci->animations[ newAnimation ];
  140.  
  141.     lf->animation = anim;
  142.     lf->animationTime = lf->frameTime + anim->initialLerp;
  143. }
  144.  
  145.  
  146. /*
  147. ===============
  148. UI_RunLerpFrame
  149. ===============
  150. */
  151. static void UI_RunLerpFrame( playerInfo_t *ci, lerpFrame_t *lf, int newAnimation ) {
  152.     int            f;
  153.     animation_t    *anim;
  154.  
  155.     // see if the animation sequence is switching
  156.     if ( newAnimation != lf->animationNumber || !lf->animation ) {
  157.         UI_SetLerpFrameAnimation( ci, lf, newAnimation );
  158.     }
  159.  
  160.     f = 0;
  161.  
  162.     // if we have passed the current frame, move it to
  163.     // oldFrame and calculate a new frame
  164.     if ( dp_realtime >= lf->frameTime ) {
  165.         lf->oldFrame = lf->frame;
  166.         lf->oldFrameTime = lf->frameTime;
  167.  
  168.         // get the next frame based on the animation
  169.         anim = lf->animation;
  170.         if (lf->animation->numFrames)
  171.         {
  172.             if ( dp_realtime < lf->animationTime ) {
  173.                 lf->frameTime = lf->animationTime;        // initial lerp
  174.             } else {
  175.                 lf->frameTime = lf->oldFrameTime + anim->frameLerp;
  176.             }
  177.             f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp;
  178.  
  179.             if ( f >= anim->numFrames ) {
  180.                 f -= anim->numFrames;
  181.                 if ( anim->loopFrames != -1 ) //Before 0 meant no loop
  182.                 {
  183.                     if(anim->numFrames - anim->loopFrames == 0)
  184.                     {
  185.                         f %= anim->numFrames;
  186.                     }
  187.                     else
  188.                     {
  189.                         f %= (anim->numFrames - anim->loopFrames);
  190.                     }
  191.                     f += anim->loopFrames;
  192.                 } 
  193.                 else 
  194.                 {
  195.                     f = anim->numFrames - 1;
  196.                     // the animation is stuck at the end, so it
  197.                     // can immediately transition to another sequence
  198.                     lf->frameTime = dp_realtime;
  199.                 }
  200.             }
  201.         }
  202.  
  203.         lf->frame = anim->firstFrame + f;
  204.         if ( dp_realtime > lf->frameTime ) {
  205.             lf->frameTime = dp_realtime;
  206.         }
  207.     }
  208.  
  209.     if ( lf->frameTime > dp_realtime + 200 ) {
  210.         lf->frameTime = dp_realtime;
  211.     }
  212.  
  213.     if ( lf->oldFrameTime > dp_realtime ) {
  214.         lf->oldFrameTime = dp_realtime;
  215.     }
  216.     // calculate current lerp value
  217.     if ( lf->frameTime == lf->oldFrameTime ) {
  218.         lf->backlerp = 0;
  219.     } else {
  220.         lf->backlerp = 1.0 - (float)( dp_realtime - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime );
  221.     }
  222. }
  223.  
  224.  
  225. /*
  226. ===============
  227. UI_PlayerAnimation
  228. ===============
  229. */
  230. static void UI_PlayerAnimation( playerInfo_t *pi, int *legsOld, int *legs, float *legsBackLerp,
  231.                         int *torsoOld, int *torso, float *torsoBackLerp ) 
  232. {
  233.  
  234.     // legs animation
  235.     pi->legsAnimationTimer -= uiInfo.uiDC.frameTime;
  236.     if ( pi->legsAnimationTimer < 0 ) {
  237.         pi->legsAnimationTimer = 0;
  238.     }
  239.  
  240.     UI_LegsSequencing( pi );
  241.  
  242.     if ( pi->legs.yawing && ( pi->legsAnim & ~ANIM_TOGGLEBIT ) == TORSO_IDLE_PISTOL ) {
  243.         UI_RunLerpFrame( pi, &pi->legs, TORSO_IDLE_PISTOL );
  244.     } else {
  245.         UI_RunLerpFrame( pi, &pi->legs, pi->legsAnim );
  246.     }
  247.     *legsOld = pi->legs.oldFrame;
  248.     *legs = pi->legs.frame;
  249.     *legsBackLerp = pi->legs.backlerp;
  250.  
  251.     // torso animation
  252.     pi->torsoAnimationTimer -= uiInfo.uiDC.frameTime;
  253.     if ( pi->torsoAnimationTimer < 0 ) {
  254.         pi->torsoAnimationTimer = 0;
  255.     }
  256.  
  257.     UI_TorsoSequencing( pi );
  258.  
  259.     UI_RunLerpFrame( pi, &pi->torso, pi->torsoAnim );
  260.     *torsoOld = pi->torso.oldFrame;
  261.     *torso = pi->torso.frame;
  262.     *torsoBackLerp = pi->torso.backlerp;
  263. }
  264.  
  265.  
  266. /*
  267. ==================
  268. UI_SwingAngles
  269. ==================
  270. */
  271. static void UI_SwingAngles( float destination, float swingTolerance, float clampTolerance,
  272.                     float speed, float *angle, qboolean *swinging ) {
  273.     float    swing;
  274.     float    move;
  275.     float    scale;
  276.  
  277.     if ( !*swinging ) {
  278.         // see if a swing should be started
  279.         swing = AngleSubtract( *angle, destination );
  280.         if ( swing > swingTolerance || swing < -swingTolerance ) {
  281.             *swinging = qtrue;
  282.         }
  283.     }
  284.  
  285.     if ( !*swinging ) {
  286.         return;
  287.     }
  288.     
  289.     // modify the speed depending on the delta
  290.     // so it doesn't seem so linear
  291.     swing = AngleSubtract( destination, *angle );
  292.     scale = fabs( swing );
  293.     if ( scale < swingTolerance * 0.5 ) {
  294.         scale = 0.5;
  295.     } else if ( scale < swingTolerance ) {
  296.         scale = 1.0;
  297.     } else {
  298.         scale = 2.0;
  299.     }
  300.  
  301.     // swing towards the destination angle
  302.     if ( swing >= 0 ) {
  303.         move = uiInfo.uiDC.frameTime * scale * speed;
  304.         if ( move >= swing ) {
  305.             move = swing;
  306.             *swinging = qfalse;
  307.         }
  308.         *angle = AngleMod( *angle + move );
  309.     } else if ( swing < 0 ) {
  310.         move = uiInfo.uiDC.frameTime * scale * -speed;
  311.         if ( move <= swing ) {
  312.             move = swing;
  313.             *swinging = qfalse;
  314.         }
  315.         *angle = AngleMod( *angle + move );
  316.     }
  317.  
  318.     // clamp to no more than tolerance
  319.     swing = AngleSubtract( destination, *angle );
  320.     if ( swing > clampTolerance ) {
  321.         *angle = AngleMod( destination - (clampTolerance - 1) );
  322.     } else if ( swing < -clampTolerance ) {
  323.         *angle = AngleMod( destination + (clampTolerance - 1) );
  324.     }
  325. }
  326.  
  327.  
  328. /*
  329. ======================
  330. UI_MovedirAdjustment
  331. ======================
  332. */
  333. static float UI_MovedirAdjustment( playerInfo_t *pi ) {
  334.     vec3_t        relativeAngles;
  335.     vec3_t        moveVector;
  336.  
  337.     VectorSubtract( pi->viewAngles, pi->moveAngles, relativeAngles );
  338.     AngleVectors( relativeAngles, moveVector, NULL, NULL );
  339.     if ( Q_fabs( moveVector[0] ) < 0.01 ) {
  340.         moveVector[0] = 0.0;
  341.     }
  342.     if ( Q_fabs( moveVector[1] ) < 0.01 ) {
  343.         moveVector[1] = 0.0;
  344.     }
  345.  
  346.     if ( moveVector[1] == 0 && moveVector[0] > 0 ) {
  347.         return 0;
  348.     }
  349.     if ( moveVector[1] < 0 && moveVector[0] > 0 ) {
  350.         return 22;
  351.     }
  352.     if ( moveVector[1] < 0 && moveVector[0] == 0 ) {
  353.         return 45;
  354.     }
  355.     if ( moveVector[1] < 0 && moveVector[0] < 0 ) {
  356.         return -22;
  357.     }
  358.     if ( moveVector[1] == 0 && moveVector[0] < 0 ) {
  359.         return 0;
  360.     }
  361.     if ( moveVector[1] > 0 && moveVector[0] < 0 ) {
  362.         return 22;
  363.     }
  364.     if ( moveVector[1] > 0 && moveVector[0] == 0 ) {
  365.         return  -45;
  366.     }
  367.  
  368.     return -22;
  369. }
  370.  
  371.  
  372. /*
  373. ===============
  374. UI_PlayerAngles
  375. ===============
  376. */
  377. static void UI_PlayerAngles( playerInfo_t *pi, vec3_t legs[3], vec3_t torso[3], vec3_t head[3] ) {
  378.     vec3_t        legsAngles, torsoAngles, headAngles;
  379.     float        dest;
  380.     float        adjust;
  381.  
  382.     VectorCopy( pi->viewAngles, headAngles );
  383.     headAngles[YAW] = AngleMod( headAngles[YAW] );
  384.     VectorClear( legsAngles );
  385.     VectorClear( torsoAngles );
  386.  
  387.     // --------- yaw -------------
  388.  
  389.     // allow yaw to drift a bit
  390.     if ( ( pi->legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_WALK ) 
  391.     {
  392.         // if not standing still, always point all in the same direction
  393.         pi->torso.yawing = qtrue;    // always center
  394.         pi->torso.pitching = qtrue;    // always center
  395.         pi->legs.yawing = qtrue;    // always center
  396.     }
  397.  
  398.     // adjust legs for movement dir
  399.     adjust = UI_MovedirAdjustment( pi );
  400.     legsAngles[YAW] = headAngles[YAW] + adjust;
  401.     torsoAngles[YAW] = headAngles[YAW] + 0.25 * adjust;
  402.  
  403.  
  404.     // torso
  405.     UI_SwingAngles( torsoAngles[YAW], 25, 90, SWINGSPEED, &pi->torso.yawAngle, &pi->torso.yawing );
  406.     UI_SwingAngles( legsAngles[YAW], 40, 90, SWINGSPEED, &pi->legs.yawAngle, &pi->legs.yawing );
  407.  
  408.     torsoAngles[YAW] = pi->torso.yawAngle;
  409.     legsAngles[YAW] = pi->legs.yawAngle;
  410.  
  411.     // --------- pitch -------------
  412.  
  413.     // only show a fraction of the pitch angle in the torso
  414.     if ( headAngles[PITCH] > 180 ) {
  415.         dest = (-360 + headAngles[PITCH]) * 0.75;
  416.     } else {
  417.         dest = headAngles[PITCH] * 0.75;
  418.     }
  419.     UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
  420.     torsoAngles[PITCH] = pi->torso.pitchAngle;
  421.  
  422.     // pull the angles back out of the hierarchial chain
  423.     AnglesSubtract( headAngles, torsoAngles, headAngles );
  424.     AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
  425.     AnglesToAxis( legsAngles, legs );
  426.     AnglesToAxis( torsoAngles, torso );
  427.     AnglesToAxis( headAngles, head );
  428. }
  429.  
  430.  
  431. /*
  432. ===============
  433. UI_PlayerFloatSprite
  434. ===============
  435. */
  436. static void UI_PlayerFloatSprite( playerInfo_t *pi, vec3_t origin, qhandle_t shader ) {
  437.     refEntity_t        ent;
  438.  
  439.     memset( &ent, 0, sizeof( ent ) );
  440.     VectorCopy( origin, ent.origin );
  441.     ent.origin[2] += 48;
  442.     ent.reType = RT_SPRITE;
  443.     ent.customShader = shader;
  444.     ent.radius = 10;
  445.     ent.renderfx = 0;
  446.     trap_R_AddRefEntityToScene( &ent );
  447. }
  448.  
  449.  
  450. /*
  451. ======================
  452. UI_MachinegunSpinAngle
  453. ======================
  454. */
  455. float    UI_MachinegunSpinAngle( playerInfo_t *pi ) {
  456.     int        delta;
  457.     float    angle;
  458.     float    speed;
  459.     int        torsoAnim;
  460.  
  461.     delta = dp_realtime - pi->barrelTime;
  462.     if ( pi->barrelSpinning ) {
  463.         angle = pi->barrelAngle + delta * SPIN_SPEED;
  464.     } else {
  465.         if ( delta > COAST_TIME ) {
  466.             delta = COAST_TIME;
  467.         }
  468.  
  469.         speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME );
  470.         angle = pi->barrelAngle + delta * speed;
  471.     }
  472.  
  473.     torsoAnim = pi->torsoAnim  & ~ANIM_TOGGLEBIT;
  474.  
  475.     return angle;
  476. }
  477.  
  478.  
  479. /*
  480. ===============
  481. UI_DrawPlayer
  482. ===============
  483. */
  484. void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) 
  485. {
  486.     refdef_t        refdef;
  487.     refEntity_t        legs;
  488.     refEntity_t        torso;
  489.     refEntity_t        head;
  490.     refEntity_t        gun;
  491.     vec3_t            origin;
  492.     int                renderfx;
  493.     vec3_t            mins = {-16, -16, -24};
  494.     vec3_t            maxs = {16, 16, 32};
  495.     float            len;
  496.     float            xx;
  497.     animation_t        *anim;
  498.     float            animSpeed;
  499.     int                flags=BONE_ANIM_OVERRIDE_FREEZE;
  500.  
  501.     if ( !pi->playerG2Model ) // || !pi->animations[0].numFrames ) 
  502.     {
  503.         return;
  504.     }
  505.  
  506.     // this allows the ui to cache the player model on the main menu
  507.     if (w == 0 || h == 0) {
  508.         return;
  509.     }
  510.  
  511.     dp_realtime = time;
  512.  
  513.     if ( pi->pendingWeapon != -1 && dp_realtime > pi->weaponTimer ) {
  514.         pi->weapon = pi->pendingWeapon;
  515.         pi->lastWeapon = pi->pendingWeapon;
  516.         pi->pendingWeapon = -1;
  517.         pi->weaponTimer = 0;
  518.     }
  519.  
  520.     UI_AdjustFrom640( &x, &y, &w, &h );
  521.  
  522.     y -= jumpHeight;
  523.  
  524.     memset( &refdef, 0, sizeof( refdef ) );
  525.     memset( &legs, 0, sizeof(legs) );
  526.     memset( &torso, 0, sizeof(torso) );
  527.     memset( &head, 0, sizeof(head) );
  528.  
  529.     refdef.rdflags = RDF_NOWORLDMODEL;
  530.  
  531.     AxisClear( refdef.viewaxis );
  532.  
  533.     refdef.x = x;
  534.     refdef.y = y;
  535.     refdef.width = w;
  536.     refdef.height = h;
  537.  
  538.     refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
  539.     xx = refdef.width / tan( refdef.fov_x / 360 * M_PI );
  540.     refdef.fov_y = atan2( refdef.height, xx );
  541.     refdef.fov_y *= ( 360 / (float)M_PI );
  542.  
  543.     // calculate distance so the player nearly fills the box
  544.     len = 0.8f * ( maxs[2] - mins[2] );        
  545.     origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 );
  546.     origin[1] = 0.5 * ( mins[1] + maxs[1] );
  547.     origin[2] = -0.5 * ( mins[2] + maxs[2] );
  548.  
  549.     refdef.time = dp_realtime;
  550.  
  551.     trap_R_ClearScene();
  552.  
  553.     // get the rotation information
  554.     UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis );
  555.     
  556.     // get the animation state (after rotation, to allow feet shuffle)
  557.     UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp,
  558.          &torso.oldframe, &torso.frame, &torso.backlerp );
  559.  
  560.     renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW | RF_MINLIGHT;
  561.  
  562.     //
  563.     // add the legs
  564.     //
  565. //    legs.hModel = pi->playerModel;
  566. //    legs.customSkin = pi->legsSkin;
  567.     legs.ghoul2 = pi->playerG2Model;
  568.  
  569. //    lf->animation = anim;
  570. //    lf->animationTime = lf->frameTime + anim->initialLerp;
  571.  
  572.     anim = pi->legs.animation;
  573.     animSpeed = 50.0f / anim->frameLerp;
  574.     if (anim->loopFrames != -1)
  575.     {
  576.         flags = BONE_ANIM_OVERRIDE_LOOP;
  577.     }
  578.  
  579.     // Temp
  580. //        flags |= BONE_ANIM_BLEND;
  581.  
  582. /*    if (torsoOnly)
  583.     {
  584.         trap_G2API_SetBoneAnim(cent->ghoul2, 0, "upper_lumbar", anim->firstFrame, anim->firstFrame + anim->numFrames, flags, animSpeed, lf->frameTime, -1, 150);
  585.     }*/
  586. //    else
  587.     if ( pi->legsOldAnim != pi->legs.animationNumber )
  588.     {
  589.         trap_G2API_SetBoneAnim( legs.ghoul2, 0, "model_root", 
  590.                                 anim->firstFrame, 
  591.                                 anim->firstFrame + anim->numFrames, 
  592.                                 flags, animSpeed, pi->legs.frameTime / 10, -1, 150);
  593.         pi->legsOldAnim = pi->legs.animationNumber;
  594.     }
  595.  
  596.     VectorCopy( origin, legs.origin );
  597.  
  598.     VectorCopy( origin, legs.lightingOrigin );
  599.     legs.renderfx = renderfx;
  600.     VectorCopy (legs.origin, legs.oldorigin);
  601.  
  602.     trap_R_AddRefEntityToScene( &legs );
  603.  
  604. //    if (!legs.hModel) {
  605. //        return;
  606. //    }
  607.  
  608.     //
  609.     // add the gun
  610.     //
  611.     if ( pi->currentWeapon != WP_NONE ) {
  612.         memset( &gun, 0, sizeof(gun) );
  613. //        gun.hModel = pi->weaponModel;
  614. //        VectorCopy( origin, gun.lightingOrigin );
  615.         gun.ghoul2 = pi->weaponG2Model;
  616.  
  617.         // NOTENOTE Need to change this to a bolt position on player model
  618. //rjr        UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon");
  619.         gun.renderfx = renderfx;
  620.         trap_R_AddRefEntityToScene( &gun );
  621.     }
  622.  
  623.     //
  624.     // add the chat icon
  625.     //
  626.     if ( pi->chat ) {
  627.         UI_PlayerFloatSprite( pi, origin, trap_R_RegisterShaderNoMip( "sprites/balloon3" ) );
  628.     }
  629.  
  630.     //
  631.     // add an accent light
  632.     //
  633.     origin[0] -= 100;    // + = behind, - = in front
  634.     origin[1] += 100;    // + = left, - = right
  635.     origin[2] += 100;    // + = above, - = below
  636.     trap_R_AddLightToScene( origin, 500, 0.5, 0.5, 0.5 );
  637.  
  638.     origin[0] -= 100;
  639.     origin[1] -= 100;
  640.     origin[2] -= 100;
  641.     trap_R_AddLightToScene( origin, 500, 0.5, 0.5, 0.5 );
  642.  
  643.     trap_R_RenderScene( &refdef );
  644. }
  645.  
  646. /*
  647. ==========================
  648. UI_FileExists
  649. ==========================
  650. */
  651. static qboolean    UI_FileExists(const char *filename) {
  652.     int len;
  653.     fileHandle_t    f;
  654.  
  655.     len = trap_FS_FOpenFile( filename, &f, FS_READ );
  656.     if (len>0) {
  657.         trap_FS_FCloseFile(f);
  658.         return qtrue;
  659.     }
  660.     return qfalse;
  661. }
  662.  
  663. /*
  664. ==========================
  665. UI_RegisterClientIdentity
  666. ==========================
  667. */
  668. qboolean UI_RegisterClientIdentity ( playerInfo_t *pi, const char* identityName ) 
  669. {
  670.     char filename[MAX_QPATH];
  671.  
  672.     if (pi->playerG2Model)
  673.     {
  674.         trap_G2API_CleanGhoul2Models(&pi->playerG2Model);
  675.         pi->playerG2Model = NULL;
  676.     }
  677.  
  678.     pi->playerG2Model = UI_RegisterIdentity ( identityName, filename );
  679.     if ( !pi->playerG2Model )
  680.     {
  681.         Com_Printf( "Failed to read Ghoul2 Skin%s\n", filename );
  682.         return qfalse;
  683.     }
  684.  
  685.     // load the animations
  686.     if ( !BG_ParseAnimationFile( filename, pi->animations ) ) 
  687.     {
  688.         Com_Printf( "Failed to load animation file %s\n", filename );
  689.         return qfalse;
  690.     }
  691.  
  692.     pi->legsOldAnim = 0;
  693.  
  694.     return qtrue;
  695. }
  696.  
  697.  
  698. /*
  699. ===============
  700. UI_PlayerInfo_SetIdentity
  701. ===============
  702. */
  703. void UI_PlayerInfo_SetIdentity ( playerInfo_t *pi, const char *identity ) 
  704. {
  705.     memset( pi, 0, sizeof(*pi) );
  706.     UI_RegisterClientIdentity ( pi, identity );
  707.     pi->weapon = WP_FIRST_RANGED_WEAPON;
  708.     pi->currentWeapon = pi->weapon;
  709.     pi->lastWeapon = pi->weapon;
  710.     pi->pendingWeapon = -1;
  711.     pi->weaponTimer = 0;
  712.     pi->chat = qfalse;
  713.     pi->newModel = qtrue;
  714. }
  715.  
  716.  
  717. /*
  718. ===============
  719. UI_PlayerInfo_SetInfo
  720. ===============
  721. */
  722. void UI_PlayerInfo_SetInfo( playerInfo_t *pi, int legsAnim, int torsoAnim, vec3_t viewAngles, vec3_t moveAngles, weapon_t weaponNumber, qboolean chat ) {
  723.     int            currentAnim;
  724.     weapon_t    weaponNum;
  725.  
  726.     pi->chat = chat;
  727.  
  728.     // view angles
  729.     VectorCopy( viewAngles, pi->viewAngles );
  730.  
  731.     // move angles
  732.     VectorCopy( moveAngles, pi->moveAngles );
  733.  
  734.     if ( pi->newModel ) {
  735.         pi->newModel = qfalse;
  736.  
  737.         jumpHeight = 0;
  738.         pi->pendingLegsAnim = 0;
  739.         UI_ForceLegsAnim( pi, legsAnim );
  740.         pi->legs.yawAngle = viewAngles[YAW];
  741.         pi->legs.yawing = qfalse;
  742.  
  743.         pi->pendingTorsoAnim = 0;
  744.         UI_ForceTorsoAnim( pi, torsoAnim );
  745.         pi->torso.yawAngle = viewAngles[YAW];
  746.         pi->torso.yawing = qfalse;
  747.  
  748.         if ( weaponNumber != -1 ) {
  749.             pi->weapon = weaponNumber;
  750.             pi->currentWeapon = weaponNumber;
  751.             pi->lastWeapon = weaponNumber;
  752.             pi->pendingWeapon = -1;
  753.             pi->weaponTimer = 0;
  754.         }
  755.  
  756.         return;
  757.     }
  758.  
  759.     // weapon
  760.     if ( weaponNumber == -1 ) {
  761.         pi->pendingWeapon = -1;
  762.         pi->weaponTimer = 0;
  763.     }
  764.     else if ( weaponNumber != WP_NONE ) {
  765.         pi->pendingWeapon = weaponNumber;
  766.         pi->weaponTimer = dp_realtime + UI_TIMER_WEAPON_DELAY;
  767.     }
  768.     weaponNum = pi->lastWeapon;
  769.     pi->weapon = weaponNum;
  770.  
  771.     if ( torsoAnim == BOTH_DEATH_CHEST_1 || legsAnim == BOTH_DEATH_CHEST_1 ) 
  772.     {
  773.         torsoAnim = legsAnim = BOTH_DEATH_CHEST_1;
  774.         pi->weapon = pi->currentWeapon = WP_NONE;
  775.  
  776.         jumpHeight = 0;
  777.         pi->pendingLegsAnim = 0;
  778.         UI_ForceLegsAnim( pi, legsAnim );
  779.  
  780.         pi->pendingTorsoAnim = 0;
  781.         UI_ForceTorsoAnim( pi, torsoAnim );
  782.  
  783.         return;
  784.     }
  785.  
  786.     // leg animation
  787.     currentAnim = pi->legsAnim & ~ANIM_TOGGLEBIT;
  788.     if ( legsAnim != LEGS_JUMP && ( currentAnim == LEGS_JUMP ) ) 
  789.     {
  790.         pi->pendingLegsAnim = legsAnim;
  791.     }
  792.     else if ( legsAnim != currentAnim ) {
  793.         jumpHeight = 0;
  794.         pi->pendingLegsAnim = 0;
  795.         UI_ForceLegsAnim( pi, legsAnim );
  796.     }
  797.  
  798.     // torso animation
  799.     if ( torsoAnim == TORSO_IDLE_PISTOL ) 
  800.     {
  801.         if ( weaponNum == WP_NONE || weaponNum == WP_KNIFE ) 
  802.         {
  803.             torsoAnim = TORSO_IDLE_PISTOL;
  804.         }
  805.         else 
  806.         {
  807.             torsoAnim = TORSO_IDLE_PISTOL;
  808.         }
  809.     }
  810.  
  811.     currentAnim = pi->torsoAnim & ~ANIM_TOGGLEBIT;
  812.  
  813.     if ( torsoAnim != currentAnim ) 
  814.     {
  815.         pi->pendingTorsoAnim = 0;
  816.         UI_ForceTorsoAnim( pi, torsoAnim );
  817.     }
  818. }
  819.  
  820. /*
  821. ===============
  822. UI_LoadIdentityIcons
  823. ===============
  824. */
  825. void UI_LoadIdentityIcons ( void )
  826. {
  827.     int        i;
  828.     char    fileName[MAX_OSPATH];
  829.     
  830. #ifdef SPECIAL_PRE_CACHE
  831.     return;
  832. #endif
  833.  
  834.     for ( i = 0; i < bg_identityCount; i ++ )
  835.     {    
  836.         Com_sprintf(fileName, sizeof(fileName), "gfx/playericons/%s ( %s ).JPG", bg_identities[i].mCharacter->mName, bg_identities[i].mSkin->mSkin);
  837.         bg_identities[i].mIcon = trap_R_RegisterShaderNoMip(fileName);
  838.     }
  839. }
  840.  
  841.  
  842. /*
  843. =================
  844. UI_ProcessIdentityItems
  845.  
  846. Attaches all the items for a character skin
  847. =================
  848. */
  849. static void UI_ProcessIdentityItems ( TGhoul2 ghoul2, TInventoryTemplate *items )
  850. {
  851.     int                modelIndex;
  852.     int                boltIndex;
  853.     TSurfaceList    *surf;
  854.  
  855.     while ( items )
  856.     {
  857.         if ( items->mItem )
  858.         {
  859.             if ( items->mItem->mModel && items->mBolt )
  860.             {
  861.                 modelIndex = trap_G2API_InitGhoul2Model(&ghoul2, items->mItem->mModel, 0, 0, 0, 0, 0);
  862.                 if (modelIndex != -1)
  863.                 {
  864.                     boltIndex = trap_G2API_AddBolt ( ghoul2, 0, items->mBolt);
  865.                     if (boltIndex != -1)
  866.                     {
  867.                         trap_G2API_AttachG2Model( ghoul2, modelIndex, ghoul2, boltIndex, 0);
  868.                     }
  869.                 }
  870.             }
  871.  
  872.             surf = items->mItem->mOffList;
  873.             while(surf)
  874.             {
  875.                 trap_G2API_SetSurfaceOnOff( ghoul2, 0, surf->mName, G2SURFACEFLAG_OFF);
  876.  
  877.                 surf = surf->mNext;
  878.             }
  879.  
  880.             surf = items->mItem->mOnList;
  881.             while(surf)
  882.             {
  883.                 trap_G2API_SetSurfaceOnOff( ghoul2, 0, surf->mName, 0);
  884.  
  885.                 surf = surf->mNext;
  886.             }
  887.         }
  888.  
  889.         items = items->mNext;
  890.     }
  891. }
  892.  
  893. /*
  894. =================
  895. UI_RegisterIdentity
  896.  
  897. Registers an identity
  898. =================
  899. */
  900. TGhoul2 UI_RegisterIdentity ( const char *identityName, char *animationFile )
  901. {
  902.     char                name[MAX_QPATH];
  903.     TGenericParser2        skinFile;
  904.     TGPGroup            *basegroup, *group, *sub;
  905.     char                temp[20480], *end;
  906.     int                    numPairs;
  907.     TIdentity            *identity;
  908.     TGhoul2                ghoul2Ptr;
  909.  
  910.     numPairs   = 0;
  911.     end           = temp;
  912.     *end       = 0;
  913.     ghoul2Ptr  = NULL;
  914.  
  915.     *animationFile = 0;
  916.  
  917.     // Find the identity in question
  918.     identity = BG_FindIdentity( identityName );
  919.     if (!identity )
  920.     {
  921.         return NULL;
  922.     }
  923.  
  924.     if (trap_G2API_InitGhoul2Model( &ghoul2Ptr, identity->mCharacter->mModel, 0, 0, 0, (1<<4), 0) == -1)
  925.     {
  926.         return NULL;
  927.     }
  928.  
  929. #ifdef SPECIAL_PRE_CACHE
  930.     Com_sprintf(temp, sizeof(temp), "gfx/playericons/%s ( %s ).JPG", identity->mCharacter->mName, identity->mSkin->mSkin);
  931.     identity->mIcon = trap_R_RegisterShaderNoMip(temp);
  932. #endif
  933.     
  934.     trap_G2API_GetAnimFileNameIndex( ghoul2Ptr, 0, name );
  935.     Com_sprintf(animationFile, MAX_QPATH, "%s_mp.cfg", name );
  936.  
  937.     if ( identity->mCharacter->mParent)
  938.     {
  939.         UI_ProcessIdentityItems( ghoul2Ptr, identity->mCharacter->mParent->mInventory );
  940.     }
  941.  
  942.     UI_ProcessIdentityItems( ghoul2Ptr, identity->mCharacter->mInventory);
  943.     UI_ProcessIdentityItems( ghoul2Ptr, identity->mSkin->mInventory);
  944.  
  945.     // don't need the mouth
  946.     trap_G2API_SetSurfaceOnOff( ghoul2Ptr, 0, "mouth_r", G2SURFACEFLAG_OFF|G2SURFACEFLAG_NODESCENDANTS);
  947.     trap_G2API_SetSurfaceOnOff( ghoul2Ptr, 0, "mouth_l", G2SURFACEFLAG_OFF|G2SURFACEFLAG_NODESCENDANTS);
  948.  
  949.     // Parse the g2skin file
  950.     Com_sprintf( name, sizeof(name), "models/characters/skins/%s.g2skin", identity->mSkin->mSkin );
  951.     skinFile = trap_GP_ParseFile( name, qtrue, qfalse );
  952.     if ( !skinFile )
  953.     {
  954.         trap_G2API_CleanGhoul2Models( &ghoul2Ptr);
  955.         return NULL;
  956.     }
  957.  
  958.     basegroup = trap_GP_GetBaseParseGroup ( skinFile );
  959.     group = trap_GPG_GetSubGroups ( basegroup );
  960.  
  961.     while(group)
  962.     {
  963.         trap_GPG_GetName ( group, name );
  964.  
  965.         // Parse the material
  966.         if ( Q_stricmp ( name, "material") == 0)
  967.         {
  968.             char    matName[MAX_QPATH];
  969.             char    shaderName[MAX_QPATH];
  970.  
  971.             trap_GPG_FindPairValue ( group, "name", "", matName );
  972.  
  973.             sub = trap_GPG_FindSubGroup ( group, "group");
  974.             if (sub)
  975.             {
  976.                 trap_GPG_FindPairValue ( sub, "shader1", "", shaderName );
  977.                 if (!shaderName[0])
  978.                 {
  979.                     trap_GPG_FindPairValue ( sub, "texture1", "", shaderName );
  980.                 }
  981.             }
  982.  
  983.             if (matName[0] && shaderName[0])
  984.             {
  985.                 end += Com_sprintf(end, sizeof(temp) - (end-temp+1), "%s %s ", matName, shaderName);
  986.                 numPairs++;
  987.             }
  988.         }
  989.  
  990.         group = trap_GPG_GetNext ( group );
  991.     }
  992.  
  993.     trap_GP_Delete(&skinFile);
  994.  
  995.     if (numPairs)
  996.     {
  997.         qhandle_t    handle;
  998.  
  999.         handle = trap_G2API_RegisterSkin( identity->mName, numPairs, temp);
  1000.         trap_G2API_SetSkin( ghoul2Ptr, 0, handle);
  1001.     }
  1002.  
  1003.     return ghoul2Ptr;
  1004. }
  1005.